<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>C# SerialPort使用指南</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#165DFF',
                        secondary: '#0FC6C2',
                        accent: '#722ED1',
                        dark: '#1D2129',
                        light: '#F2F3F5'
                    },
                    fontFamily: {
                        inter: ['Inter', 'system-ui', 'sans-serif'],
                    },
                }
            }
        }
    </script>
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto {
                content-visibility: auto;
            }
            .text-shadow {
                text-shadow: 0 2px 4px rgba(0,0,0,0.1);
            }
            .card-hover {
                transition: all 0.3s ease;
            }
            .card-hover:hover {
                transform: translateY(-5px);
                box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
            }
        }
    </style>
</head>
<body class="font-inter bg-gray-50 text-dark">
    <!-- 导航栏 -->
    <header class="sticky top-0 z-50 bg-white shadow-md">
        <nav class="container mx-auto px-4 py-3 flex justify-between items-center">
            <div class="flex items-center space-x-2">
                <i class="fa fa-microchip text-primary text-2xl"></i>
                <h1 class="text-xl md:text-2xl font-bold text-primary">C# SerialPort<span class="text-dark">使用指南</span></h1>
            </div>
            <div class="hidden md:flex space-x-8">
                <a href="#overview" class="text-gray-600 hover:text-primary transition-colors">概述</a>
                <a href="#properties" class="text-gray-600 hover:text-primary transition-colors">属性详解</a>
                <a href="#usage" class="text-gray-600 hover:text-primary transition-colors">基本使用</a>
                <a href="#example" class="text-gray-600 hover:text-primary transition-colors">完整案例</a>
                <a href="#notes" class="text-gray-600 hover:text-primary transition-colors">注意事项</a>
            </div>
            <button class="md:hidden text-gray-600" id="mobile-menu-button">
                <i class="fa fa-bars text-xl"></i>
            </button>
        </nav>
        <!-- 移动端菜单 -->
        <div class="md:hidden hidden bg-white border-t" id="mobile-menu">
            <div class="container mx-auto px-4 py-3 flex flex-col space-y-3">
                <a href="#overview" class="text-gray-600 hover:text-primary py-2 transition-colors">概述</a>
                <a href="#properties" class="text-gray-600 hover:text-primary py-2 transition-colors">属性详解</a>
                <a href="#usage" class="text-gray-600 hover:text-primary py-2 transition-colors">基本使用</a>
                <a href="#example" class="text-gray-600 hover:text-primary py-2 transition-colors">完整案例</a>
                <a href="#notes" class="text-gray-600 hover:text-primary py-2 transition-colors">注意事项</a>
            </div>
        </div>
    </header>

    <main class="container mx-auto px-4 py-8">
        <!-- 英雄区 -->
        <section class="mb-16 text-center">
            <div class="max-w-3xl mx-auto">
                <h1 class="text-[clamp(2rem,5vw,3.5rem)] font-bold mb-6 text-dark">
                    C# <span class="text-primary">SerialPort</span> 类使用指南
                </h1>
                <p class="text-lg md:text-xl text-gray-600 mb-8">
                    全面掌握C#中串口通信的核心知识与实践技巧
                </p>
                <div class="flex flex-wrap justify-center gap-4">
                    <a href="#properties" class="bg-primary hover:bg-primary/90 text-white px-6 py-3 rounded-lg shadow-lg transition-all flex items-center">
                        <i class="fa fa-book mr-2"></i> 开始学习
                    </a>
                    <a href="#example" class="bg-white hover:bg-gray-100 text-primary border border-primary px-6 py-3 rounded-lg shadow-lg transition-all flex items-center">
                        <i class="fa fa-code mr-2"></i> 查看案例
                    </a>
                </div>
            </div>
        </section>

        <!-- 概述部分 -->
        <section id="overview" class="mb-16 scroll-mt-20">
            <div class="bg-white rounded-xl shadow-xl p-8 card-hover">
                <h2 class="text-3xl font-bold mb-6 text-dark flex items-center">
                    <span class="bg-primary text-white p-2 rounded-lg mr-3">
                        <i class="fa fa-info-circle"></i>
                    </span>
                    一、SerialPort类概述
                </h2>
                <p class="text-gray-700 mb-6 text-lg">
                    在C#中，<code class="bg-light px-2 py-1 rounded text-primary font-medium">SerialPort</code>类是System.IO.Ports命名空间下的一个重要类，用于实现串行端口通信。该类提供了一系列属性、方法和事件，使开发者能够方便地与串行设备（如Arduino、传感器、调制解调器等）进行数据交互。
                </p>
                <div class="bg-light rounded-lg p-6 mb-6">
                    <h3 class="text-xl font-semibold mb-4 text-dark">主要功能</h3>
                    <ul class="space-y-3">
                        <li class="flex items-start">
                            <i class="fa fa-check-circle text-green-500 mt-1 mr-3"></i>
                            <span>配置和管理串口参数（波特率、数据位、停止位等）</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fa fa-check-circle text-green-500 mt-1 mr-3"></i>
                            <span>发送和接收数据（同步或异步方式）</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fa fa-check-circle text-green-500 mt-1 mr-3"></i>
                            <span>处理串口事件（如数据接收事件）</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fa fa-check-circle text-green-500 mt-1 mr-3"></i>
                            <span>实现流控制（硬件或软件握手）</span>
                        </li>
                    </ul>
                </div>
                <div class="bg-light rounded-lg p-6">
                    <h3 class="text-xl font-semibold mb-4 text-dark">典型应用场景</h3>
                    <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
                        <div class="bg-white p-4 rounded-lg shadow-sm">
                            <div class="text-primary text-2xl mb-3">
                                <i class="fa fa-microcontroller"></i>
                            </div>
                            <h4 class="font-semibold mb-2">嵌入式系统通信</h4>
                            <p class="text-gray-600">与Arduino、Raspberry Pi等设备通信</p>
                        </div>
                        <div class="bg-white p-4 rounded-lg shadow-sm">
                            <div class="text-primary text-2xl mb-3">
                                <i class="fa fa-sensors"></i>
                            </div>
                            <h4 class="font-semibold mb-2">传感器数据采集</h4>
                            <p class="text-gray-600">读取温度、湿度、压力等传感器数据</p>
                        </div>
                        <div class="bg-white p-4 rounded-lg shadow-sm">
                            <div class="text-primary text-2xl mb-3">
                                <i class="fa fa-industry"></i>
                            </div>
                            <h4 class="font-semibold mb-2">工业自动化</h4>
                            <p class="text-gray-600">控制PLC、机器人等工业设备</p>
                        </div>
                    </div>
                </div>
            </div>
        </section>

        <!-- 属性详解部分 -->
        <section id="properties" class="mb-16 scroll-mt-20">
            <div class="bg-white rounded-xl shadow-xl p-8 card-hover">
                <h2 class="text-3xl font-bold mb-6 text-dark flex items-center">
                    <span class="bg-primary text-white p-2 rounded-lg mr-3">
                        <i class="fa fa-sliders"></i>
                    </span>
                    二、常用属性及其作用
                </h2>
                
                <div class="overflow-x-auto">
                    <table class="min-w-full divide-y divide-gray-200">
                        <thead class="bg-gray-50">
                            <tr>
                                <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">属性</th>
                                <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">作用</th>
                                <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">示例</th>
                            </tr>
                        </thead>
                        <tbody class="bg-white divide-y divide-gray-200">
                            <tr>
                                <td class="px-6 py-4 whitespace-nowrap">
                                    <div class="text-sm font-medium text-dark">PortName</div>
                                </td>
                                <td class="px-6 py-4">
                                    <div class="text-sm text-gray-700">获取或设置通信端口（如COM1、COM2、COM3等）。</div>
                                </td>
                                <td class="px-6 py-4">
                                    <div class="text-sm font-mono bg-light p-2 rounded">serialPort1.PortName = "COM3";</div>
                                </td>
                            </tr>
                            <tr>
                                <td class="px-6 py-4 whitespace-nowrap">
                                    <div class="text-sm font-medium text-dark">BaudRate</div>
                                </td>
                                <td class="px-6 py-4">
                                    <div class="text-sm text-gray-700">获取或设置串行波特率，即每秒传输的比特数。常见值有9600、115200等。</div>
                                </td>
                                <td class="px-6 py-4">
                                    <div class="text-sm font-mono bg-light p-2 rounded">serialPort1.BaudRate = 9600;</div>
                                </td>
                            </tr>
                            <tr>
                                <td class="px-6 py-4 whitespace-nowrap">
                                    <div class="text-sm font-medium text-dark">DataBits</div>
                                </td>
                                <td class="px-6 py-4">
                                    <div class="text-sm text-gray-700">获取或设置每个字节的标准数据位长度，通常为8位。</div>
                                </td>
                                <td class="px-6 py-4">
                                    <div class="text-sm font-mono bg-light p-2 rounded">serialPort1.DataBits = 8;</div>
                                </td>
                            </tr>
                            <tr>
                                <td class="px-6 py-4 whitespace-nowrap">
                                    <div class="text-sm font-medium text-dark">Parity</div>
                                </td>
                                <td class="px-6 py-4">
                                    <div class="text-sm text-gray-700">获取或设置奇偶校验检查协议。</div>
                                    <ul class="text-xs text-gray-600 mt-1 ml-4">
                                        <li>None：不进行校验（默认）。</li>
                                        <li>Odd：数据位和校验位中"1"的个数为奇数。</li>
                                        <li>Even：数据位和校验位中"1"的个数为偶数。</li>
                                    </ul>
                                </td>
                                <td class="px-6 py-4">
                                    <div class="text-sm font-mono bg-light p-2 rounded">serialPort1.Parity = Parity.None;</div>
                                </td>
                            </tr>
                            <tr>
                                <td class="px-6 py-4 whitespace-nowrap">
                                    <div class="text-sm font-medium text-dark">StopBits</div>
                                </td>
                                <td class="px-6 py-4">
                                    <div class="text-sm text-gray-700">获取或设置每个字节的标准停止位数。</div>
                                    <ul class="text-xs text-gray-600 mt-1 ml-4">
                                        <li>One：1个停止位（默认）。</li>
                                        <li>Two：2个停止位。</li>
                                        <li>OnePointFive：1.5个停止位。</li>
                                    </ul>
                                </td>
                                <td class="px-6 py-4">
                                    <div class="text-sm font-mono bg-light p-2 rounded">serialPort1.StopBits = StopBits.One;</div>
                                </td>
                            </tr>
                            <tr>
                                <td class="px-6 py-4 whitespace-nowrap">
                                    <div class="text-sm font-medium text-dark">ReadTimeout</div>
                                </td>
                                <td class="px-6 py-4">
                                    <div class="text-sm text-gray-700">获取或设置读取操作未完成时发生超时之前的毫秒数。</div>
                                </td>
                                <td class="px-6 py-4">
                                    <div class="text-sm font-mono bg-light p-2 rounded">serialPort1.ReadTimeout = 500;</div>
                                </td>
                            </tr>
                            <tr>
                                <td class="px-6 py-4 whitespace-nowrap">
                                    <div class="text-sm font-medium text-dark">WriteTimeout</div>
                                </td>
                                <td class="px-6 py-4">
                                    <div class="text-sm text-gray-700">获取或设置写入操作未完成时发生超时之前的毫秒数。</div>
                                </td>
                                <td class="px-6 py-4">
                                    <div class="text-sm font-mono bg-light p-2 rounded">serialPort1.WriteTimeout = 500;</div>
                                </td>
                            </tr>
                            <tr>
                                <td class="px-6 py-4 whitespace-nowrap">
                                    <div class="text-sm font-medium text-dark">ReadBufferSize</div>
                                </td>
                                <td class="px-6 py-4">
                                    <div class="text-sm text-gray-700">获取或设置串行端口输入缓冲区的大小。</div>
                                </td>
                                <td class="px-6 py-4">
                                    <div class="text-sm font-mono bg-light p-2 rounded">serialPort1.ReadBufferSize = 4096;</div>
                                </td>
                            </tr>
                            <tr>
                                <td class="px-6 py-4 whitespace-nowrap">
                                    <div class="text-sm font-medium text-dark">WriteBufferSize</div>
                                </td>
                                <td class="px-6 py-4">
                                    <div class="text-sm text-gray-700">获取或设置串行端口输出缓冲区的大小。</div>
                                </td>
                                <td class="px-6 py-4">
                                    <div class="text-sm font-mono bg-light p-2 rounded">serialPort1.WriteBufferSize = 2048;</div>
                                </td>
                            </tr>
                            <tr>
                                <td class="px-6 py-4 whitespace-nowrap">
                                    <div class="text-sm font-medium text-dark">Handshake</div>
                                </td>
                                <td class="px-6 py-4">
                                    <div class="text-sm text-gray-700">获取或设置串行通信中使用的握手协议。</div>
                                    <ul class="text-xs text-gray-600 mt-1 ml-4">
                                        <li>None：不使用握手协议（默认）。</li>
                                        <li>XOnXOff：使用XON/XOFF软件控制协议。</li>
                                        <li>RequestToSend：使用请求发送(RTS)硬件流控制。</li>
                                        <li>RequestToSendXOnXOff：同时使用RTS和XON/XOFF。</li>
                                    </ul>
                                </td>
                                <td class="px-6 py-4">
                                    <div class="text-sm font-mono bg-light p-2 rounded">serialPort1.Handshake = Handshake.None;</div>
                                </td>
                            </tr>
                            <tr>
                                <td class="px-6 py-4 whitespace-nowrap">
                                    <div class="text-sm font-medium text-dark">NewLine</div>
                                </td>
                                <td class="px-6 py-4">
                                    <div class="text-sm text-gray-700">获取或设置用于解释ReadLine()和WriteLine()方法调用结束的值。</div>
                                </td>
                                <td class="px-6 py-4">
                                    <div class="text-sm font-mono bg-light p-2 rounded">serialPort1.NewLine = "\r\n";</div>
                                </td>
                            </tr>
                            <tr>
                                <td class="px-6 py-4 whitespace-nowrap">
                                    <div class="text-sm font-medium text-dark">DataReceived</div>
                                </td>
                                <td class="px-6 py-4">
                                    <div class="text-sm text-gray-700">当串口接收到数据时触发的事件，需配合事件处理程序使用。</div>
                                </td>
                                <td class="px-6 py-4">
                                    <div class="text-sm font-mono bg-light p-2 rounded">
                                        serialPort1.DataReceived += new<br>
                                        &nbsp;&nbsp;SerialDataReceivedEventHandler(SerialPort1_DataReceived);
                                    </div>
                                </td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </div>
        </section>

        <!-- 基本使用部分 -->
        <section id="usage" class="mb-16 scroll-mt-20">
            <div class="bg-white rounded-xl shadow-xl p-8 card-hover">
                <h2 class="text-3xl font-bold mb-6 text-dark flex items-center">
                    <span class="bg-primary text-white p-2 rounded-lg mr-3">
                        <i class="fa fa-code"></i>
                    </span>
                    三、基本使用流程
                </h2>
                
                <div class="space-y-8">
                    <!-- 引入命名空间 -->
                    <div class="bg-light rounded-lg p-6">
                        <h3 class="text-xl font-semibold mb-4 text-dark">1. 引入命名空间</h3>
                        <pre class="bg-dark text-white p-4 rounded-lg overflow-x-auto font-mono text-sm"><code>using System.IO.Ports;</code></pre>
                    </div>
                    
                    <!-- 创建对象 -->
                    <div class="bg-light rounded-lg p-6">
                        <h3 class="text-xl font-semibold mb-4 text-dark">2. 创建SerialPort对象</h3>
                        <pre class="bg-dark text-white p-4 rounded-lg overflow-x-auto font-mono text-sm"><code>SerialPort serialPort1 = new SerialPort();</code></pre>
                    </div>
                    
                    <!-- 配置参数 -->
                    <div class="bg-light rounded-lg p-6">
                        <h3 class="text-xl font-semibold mb-4 text-dark">3. 配置串口参数</h3>
                        <pre class="bg-dark text-white p-4 rounded-lg overflow-x-auto font-mono text-sm"><code>serialPort1.PortName = "COM3";
serialPort1.BaudRate = 9600;
serialPort1.Parity = Parity.None;
serialPort1.DataBits = 8;
serialPort1.StopBits = StopBits.One;
serialPort1.Handshake = Handshake.None;</code></pre>
                    </div>
                    
                    <!-- 打开串口 -->
                    <div class="bg-light rounded-lg p-6">
                        <h3 class="text-xl font-semibold mb-4 text-dark">4. 打开串口</h3>
                        <pre class="bg-dark text-white p-4 rounded-lg overflow-x-auto font-mono text-sm"><code>try
{
    if (!serialPort1.IsOpen)
    {
        serialPort1.Open();
        Console.WriteLine("串口已打开");
    }
}
catch (Exception ex)
{
    Console.WriteLine("打开串口失败: " + ex.Message);
}</code></pre>
                    </div>
                    
                    <!-- 发送数据 -->
                    <div class="bg-light rounded-lg p-6">
                        <h3 class="text-xl font-semibold mb-4 text-dark">5. 发送数据</h3>
                        <pre class="bg-dark text-white p-4 rounded-lg overflow-x-auto font-mono text-sm"><code>// 发送字符串
string data = "Hello, Arduino!";
serialPort1.WriteLine(data);  // 使用WriteLine自动添加换行符

// 发送字节数组
byte[] buffer = Encoding.ASCII.GetBytes(data);
serialPort1.Write(buffer, 0, buffer.Length);</code></pre>
                    </div>
                    
                    <!-- 接收数据 -->
                    <div class="bg-light rounded-lg p-6">
                        <h3 class="text-xl font-semibold mb-4 text-dark">6. 接收数据</h3>
                        <pre class="bg-dark text-white p-4 rounded-lg overflow-x-auto font-mono text-sm"><code>// 同步读取（阻塞方式）
try
{
    string receivedData = serialPort1.ReadLine();
    Console.WriteLine("接收到数据: " + receivedData);
}
catch (TimeoutException)
{
    Console.WriteLine("读取超时");
}

// 异步读取（事件驱动方式）
private void SerialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    SerialPort sp = (SerialPort)sender;
    string data = sp.ReadExisting();
    // 在UI线程中更新界面
    this.Invoke(new Action(() =>
    {
        textBox1.AppendText("接收到数据: " + data + Environment.NewLine);
    }));</code></pre>
                    </div>
                    
                    <!-- 关闭串口 -->
                    <div class="bg-light rounded-lg p-6">
                        <h3 class="text-xl font-semibold mb-4 text-dark">7. 关闭串口</h3>
                        <pre class="bg-dark text-white p-4 rounded-lg overflow-x-auto font-mono text-sm"><code>if (serialPort1.IsOpen)
{
    serialPort1.Close();
    Console.WriteLine("串口已关闭");
}</code></pre>
                    </div>
                </div>
            </div>
        </section>

        <!-- 完整案例部分 -->
        <section id="example" class="mb-16 scroll-mt-20">
            <div class="bg-white rounded-xl shadow-xl p-8 card-hover">
                <h2 class="text-3xl font-bold mb-6 text-dark flex items-center">
                    <span class="bg-primary text-white p-2 rounded-lg mr-3">
                        <i class="fa fa-project-diagram"></i>
                    </span>
                    四、完整案例：C#与Arduino串口通信
                </h2>
                
                <div class="bg-light rounded-lg p-6 mb-8">
                    <h3 class="text-xl font-semibold mb-4 text-dark">案例需求</h3>
                    <p class="text-gray-700 mb-4">
                        使用C#编写一个简单的Windows窗体应用程序，与Arduino进行串口通信：
                    </p>
                    <ul class="space-y-2 ml-6 list-disc text-gray-700">
                        <li>发送控制命令（0-9）控制Arduino板载LED的亮度。</li>
                        <li>接收Arduino返回的传感器数据并显示在界面上。</li>
                    </ul>
                </div>
                
                <div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
                    <!-- Arduino端代码 -->
                    <div>
                        <div class="bg-dark rounded-lg p-6 text-white">
                            <h3 class="text-xl font-semibold mb-4 text-white flex items-center">
                                <i class="fa fa-microcontroller text-green-400 mr-3"></i>
                                Arduino端代码
                            </h3>
                            <pre class="overflow-x-auto font-mono text-sm"><code>int ledPin = 13;
int sensorPin = A0;
int sensorValue = 0;

void setup() {
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  // 读取传感器数据
  sensorValue = analogRead(sensorPin);
  
  // 发送传感器数据到PC
  Serial.print("Sensor: ");
  Serial.println(sensorValue);
  
  // 检查是否有来自PC的命令
  if (Serial.available() > 0) {
    char c = Serial.read();
    // 将字符转换为整数(0-9)
    int brightness = c - '0';
    // 映射到0-255范围
    brightness = constrain(brightness * 28, 0, 255);
    // 设置LED亮度
    analogWrite(ledPin, brightness);
  }
  
  delay(100);
}</code></pre>
                        </div>
                    </div>
                    
                    <!-- C#代码 -->
                    <div>
                        <div class="bg-dark rounded-lg p-6 text-white">
                            <h3 class="text-xl font-semibold mb-4 text-white flex items-center">
                                <i class="fa fa-code text-blue-400 mr-3"></i>
                                C# Windows窗体应用程序
                            </h3>
                            <pre class="overflow-x-auto font-mono text-sm"><code>using System;
using System.IO.Ports;
using System.Windows.Forms;

namespace SerialPortExample
{
    public partial class MainForm : Form
    {
        private SerialPort serialPort;

        public MainForm()
        {
            InitializeComponent();
            InitializeSerialPort();
        }

        private void InitializeSerialPort()
        {
            serialPort = new SerialPort();
            serialPort.BaudRate = 9600;
            serialPort.Parity = Parity.None;
            serialPort.DataBits = 8;
            serialPort.StopBits = StopBits.One;
            serialPort.Handshake = Handshake.None;
            serialPort.NewLine = "\n";
            serialPort.DataReceived += new SerialDataReceivedEventHandler(SerialPort_DataReceived);

            // 填充COM端口列表
            string[] ports = SerialPort.GetPortNames();
            comboBoxPorts.Items.AddRange(ports);
            if (ports.Length > 0)
                comboBoxPorts.SelectedIndex = 0;
        }

        private void buttonConnect_Click(object sender, EventArgs e)
        {
            try
            {
                if (!serialPort.IsOpen)
                {
                    serialPort.PortName = comboBoxPorts.SelectedItem.ToString();
                    serialPort.Open();
                    buttonConnect.Text = "断开连接";
                    textBoxStatus.Text = "已连接到 " + serialPort.PortName;
                }
                else
                {
                    serialPort.Close();
                    buttonConnect.Text = "连接";
                    textBoxStatus.Text = "未连接";
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("串口操作错误: " + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void buttonSend_Click(object sender, EventArgs e)
        {
            if (serialPort.IsOpen && !string.IsNullOrEmpty(textBoxSend.Text))
            {
                try
                {
                    // 发送数据
                    serialPort.WriteLine(textBoxSend.Text);
                    textBoxLog.AppendText("发送: " + textBoxSend.Text + Environment.NewLine);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("发送数据错误: " + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                // 读取接收到的数据
                string data = serialPort.ReadLine();
                
                // 在UI线程中更新界面
                this.Invoke(new Action(() =>
                {
                    textBoxLog.AppendText("接收: " + data);
                }));
            }
            catch (Exception ex)
            {
                MessageBox.Show("接收数据错误: " + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            // 确保在窗体关闭时关闭串口
            if (serialPort != null && serialPort.IsOpen)
            {
                serialPort.Close();
            }
        }

        private void button0_Click(object sender, EventArgs e) { SendCommand('0'); }
        private void button1_Click(object sender, EventArgs e) { SendCommand('1'); }
        private void button2_Click(object sender, EventArgs e) { SendCommand('2'); }
        private void button3_Click(object sender, EventArgs e) { SendCommand('3'); }
        private void button4_Click(object sender, EventArgs e) { SendCommand('4'); }
        private void button5_Click(object sender, EventArgs e) { SendCommand('5'); }
        private void button6_Click(object sender, EventArgs e) { SendCommand('6'); }
        private void button7_Click(object sender, EventArgs e) { SendCommand('7'); }
        private void button8_Click(object sender, EventArgs e) { SendCommand('8'); }
        private void button9_Click(object sender, EventArgs e) { SendCommand('9'); }

        private void SendCommand(char command)
        {
            if (serialPort.IsOpen)
            {
                try
                {
                    serialPort.Write(command.ToString());
                    textBoxLog.AppendText("发送命令: " + command + Environment.NewLine);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("发送命令错误: " + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }
    }
}</code></pre>
                        </div>
                    </div>
                </div>
                
                <!-- 窗体设计 -->
                <div class="bg-light rounded-lg p-6 mt-8">
                    <h3 class="text-xl font-semibold mb-4 text-dark">窗体设计</h3>
                    <p class="text-gray-700 mb-4">
                        在Windows窗体设计器中添加以下控件：
                    </p>
                    <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
                        <div class="bg-white p-4 rounded-lg shadow-sm">
                            <h4 class="font-semibold mb-2 text-dark">主要控件</h4>
                            <ul class="space-y-2 text-gray-700">
                                <li><code>ComboBox (comboBoxPorts)</code>：选择COM端口</li>
                                <li><code>Button (buttonConnect)</code>：连接/断开串口</li>
                                <li><code>TextBox (textBoxStatus)</code>：显示连接状态</li>
                                <li><code>TextBox (textBoxLog)</code>：显示通信日志</li>
                                <li><code>TextBox (textBoxSend)</code>：输入要发送的数据</li>
                                <li><code>Button (buttonSend)</code>：发送数据</li>
                            </ul>
                        </div>
                        <div class="bg-white p-4 rounded-lg shadow-sm">
                            <h4 class="font-semibold mb-2 text-dark">数字控制按钮</h4>
                            <ul class="space-y-2 text-gray-700">
                                <li><code>Button (button0-button9)</code>：发送数字命令0-9</li>
                            </ul>
                        </div>
                    </div>
                </div>
            </div>
        </section>

        <!-- 注意事项部分 -->
        <section id="notes" class="mb-16 scroll-mt-20">
            <div class="bg-white rounded-xl shadow-xl p-8 card-hover">
                <h2 class="text-3xl font-bold mb-6 text-dark flex items-center">
                    <span class="bg-primary text-white p-2 rounded-lg mr-3">
                        <i class="fa fa-exclamation-triangle"></i>
                    </span>
                    五、注意事项
                </h2>
                
                <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
                    <div class="bg-red-50 border-l-4 border-red-500 p-4 rounded-r-lg">
                        <h3 class="text-lg font-semibold text-red-800 mb-2">1. 线程安全</h3>
                        <p class="text-red-700">
                            <code>DataReceived</code>事件在辅助线程上触发，因此在事件处理程序中访问UI控件时需要使用<code>Invoke</code>方法。
                        </p>
                    </div>
                    
                    <div class="bg-yellow-50 border-l-4 border-yellow-500 p-4 rounded-r-lg">
                        <h3 class="text-lg font-semibold text-yellow-800 mb-2">2. 异常处理</h3>
                        <p class="text-yellow-700">
                            串口操作可能会抛出各种异常（如端口被占用、超时等），必须进行适当的异常处理。
                        </p>
                    </div>
                    
                    <div class="bg-green-50 border-l-4 border-green-500 p-4 rounded-r-lg">
                        <h3 class="text-lg font-semibold text-green-800 mb-2">3. 资源管理</h3>
                        <p class="text-green-700">
                            确保在不再使用串口时调用<code>Close()</code>方法释放资源，通常在窗体关闭事件中处理。
                        </p>
                    </div>
                    
                    <div class="bg-blue-50 border-l-4 border-blue-500 p-4 rounded-r-lg">
                        <h3 class="text-lg font-semibold text-blue-800 mb-2">4. 波特率匹配</h3>
                        <p class="text-blue-700">
                            C#程序和Arduino的波特率必须保持一致，否则会出现数据乱码。
                        </p>
                    </div>
                    
                    <div class="bg-purple-50 border-l-4 border-purple-500 p-4 rounded-r-lg">
                        <h3 class="text-lg font-semibold text-purple-800 mb-2">5. 数据格式</h3>
                        <p class="text-purple-700">
                            在发送和接收数据时，要明确数据格式（如字符串、字节数组），并进行相应的编码和解码。
                        </p>
                    </div>
                    
                    <div class="bg-gray-50 border-l-4 border-gray-500 p-4 rounded-r-lg">
                        <h3 class="text-lg font-semibold text-gray-800 mb-2">6. 权限问题</h3>
                        <p class="text-gray-700">
                            在某些操作系统中，访问串口可能需要管理员权限，确保程序有足够的权限访问串口设备。
                        </p>
                    </div>
                </div>
            </div>
        </section>
    </main>

    <footer class="bg-dark text-white py-12">
        <div class="container mx-auto px-4">
            <div class="flex flex-col md:flex-row justify-between items-center">
                <div class="mb-6 md:mb-0">
                    <div class="flex items-center space-x-2">
                        <i class="fa fa-microchip text-primary text-2xl"></i>
                        <h2 class="text-xl font-bold">C# SerialPort使用指南</h2>
                    </div>
                    <p class="text-gray-400 mt-2">全面掌握C#中串口通信的核心知识与实践技巧</p>
                </div>
                <div class="flex space-x-6">
                    <a href="#overview" class="text-gray-400 hover:text-white transition-colors">概述</a>
                    <a href="#properties" class="text-gray-400 hover:text-white transition-colors">属性详解</a>
                    <a href="#usage" class="text-gray-400 hover:text-white transition-colors">基本使用</a>
                    <a href="#example" class="text-gray-400 hover:text-white transition-colors">完整案例</a>
                    <a href="#notes" class="text-gray-400 hover:text-white transition-colors">注意事项</a>
                </div>
            </div>
            <div class="border-t border-gray-800 mt-8 pt-8 text-center text-gray-500">
                <p>&copy; 2025 豆包编程助手 | 本指南仅供学习参考</p>
            </div>
        </div>
    </footer>

    <script>
        // 移动端菜单切换
        document.getElementById('mobile-menu-button').addEventListener('click', function() {
            const mobileMenu = document.getElementById('mobile-menu');
            mobileMenu.classList.toggle('hidden');
        });

        // 平滑滚动
        document.querySelectorAll('a[href^="#"]').forEach(anchor => {
            anchor.addEventListener('click', function (e) {
                e.preventDefault();
                
                document.querySelector(this.getAttribute('href')).scrollIntoView({
                    behavior: 'smooth'
                });
                
                // 关闭移动端菜单
                document.getElementById('mobile-menu').classList.add('hidden');
            });
        });

        // 导航栏滚动效果
        window.addEventListener('scroll', function() {
            const header = document.querySelector('header');
            if (window.scrollY > 10) {
                header.classList.add('py-2');
                header.classList.remove('py-3');
            } else {
                header.classList.add('py-3');
                header.classList.remove('py-2');
            }
        });
    </script>
</body>
</html>
    